package me.maiz.lab.batchdemo.config;

import com.google.common.collect.ImmutableMap;
import me.maiz.lab.batchdemo.batch.JobCompletionNotificationListener;
import me.maiz.lab.batchdemo.batch.UserCreditCalcProcessor;
import me.maiz.lab.batchdemo.batch.domain.UserOrderData;
import me.maiz.lab.batchdemo.entity.User;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.batch.MyBatisBatchItemWriter;
import org.mybatis.spring.batch.MyBatisCursorItemReader;
import org.mybatis.spring.batch.builder.MyBatisBatchItemWriterBuilder;
import org.mybatis.spring.batch.builder.MyBatisCursorItemReaderBuilder;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.support.CompositeItemProcessor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Configuration
public class BatchConfig {
    // job -> step -> reader \ processer \ writer

    @Resource
    public JobBuilderFactory jobBuilderFactory;

    @Resource
    public StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job userCalcLevelJob(JobCompletionNotificationListener listener,
                                Step calcCreditStep){
        return jobBuilderFactory.get("userCalcLevelJob")
                .incrementer(new RunIdIncrementer())
                .listener(listener)
                .start(calcCreditStep)
                .build();
    }

    @Bean
    public Step calcCreditStep(
            MyBatisCursorItemReader<UserOrderData> userOrderReader,
            MyBatisBatchItemWriter<User> userWriter
            ){
        return stepBuilderFactory.get("calcCreditStep")
                .chunk(10)
                .reader(userOrderReader)
                .processor(userCreditCalcProcessor())
                .writer(userWriter)
                .build();
    }

    @Bean
    @StepScope
    public MyBatisCursorItemReader<UserOrderData> userOrderReader(SqlSessionFactory sqlSessionFactory
    , @Value("#{jobParameters[startTime]}") Date startTime
    ){
        return new MyBatisCursorItemReaderBuilder<UserOrderData>()
                .sqlSessionFactory(sqlSessionFactory)
                .queryId("me.maiz.lab.batchdemo.dao.UserBatch.queryAllUserOrder")
                .parameterValues(ImmutableMap.of("startTime",startTime))
                .build();
    }

    @Bean
    @StepScope
    public ItemProcessor userCreditCalcProcessor(){

        return new UserCreditCalcProcessor();
    }


    @Bean
    public MyBatisBatchItemWriter<User> userWriter(SqlSessionFactory sqlSessionFactory){

        return new MyBatisBatchItemWriterBuilder<User>()
                .sqlSessionFactory(sqlSessionFactory)
                .statementId("me.maiz.lab.batchdemo.dao.UserMapper.updateUserById")
                .build();
    }


}
